﻿using CloudFranceTriple.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using WebMatrix.WebData;

namespace CloudFranceTriple.WebRole.Areas.Forum.Controllers
{
    [CloudFranceTriple.WebRole.Filters.InitializeSimpleMembership]
    public class UnreadMessageController : AsyncController
    {
        private cloudfrAboq2RsDMEntities db = new cloudfrAboq2RsDMEntities();
        // Permet d'empecher de lancer plusieurs fois en parallele le marquage des messages du même utilisateur
        public static List<Int32> _UserMarkingAllAsRead = new List<Int32>();

        private readonly IWebSecurityWrapper _webSecurity;
        public UnreadMessageController()
        {
            this._webSecurity = new WebSecurityWrapper();
        }

        public UnreadMessageController(IWebSecurityWrapper webSecurity)
        {
            this._webSecurity = webSecurity;
        }

        /// <summary>
        /// Duplicate with BaseController !!!!
        /// </summary>
        /// <param name="IsAuthenticated"></param>
        /// <returns></returns>
        private List<Int32> _forumIdAllowed(Boolean IsAuthenticated)
        {
            var db = new cloudfrAboq2RsDMEntities();
            // Cas des administrateurs : accès total
            if (IsAuthenticated && User.IsInRole("RoleAdminForum"))
                return (from f in db.ForumSet
                        orderby f.OrderForum
                        select f.Id).ToList();
            // Cas des utilisateurs authentifiés et des utilisateurs anonymes
            else
            {
                String[] UserRoles = Roles.GetRolesForUser();
                if (!IsAuthenticated | UserRoles.Count() == 0)
                    UserRoles = new String[1] { "RolePublic" };

                return (from r in db.webpages_Roles
                        from rf in r.ForumSecuritySet
                        where r.RoleId == rf.webpages_Roles_RoleId
                        & UserRoles.Contains(r.RoleName)
                        select rf.ForumSet_Id).ToList();
            }
        }

        //
        // GET: /Forum/PostRead/ShowUnreadMessage

        [AllowAnonymous]
        [Authorize(Roles = "RoleMember,RoleFans,RoleBaffMember,RoleAdminForum")]
        public ActionResult ShowUnreadMessage()
        {
            Int32 UnReadPostNumber;
            String ForumPostUnreadNumber;

            if (!User.Identity.IsAuthenticated)
            {
                UnReadPostNumber = 0;
                ForumPostUnreadNumber = String.Empty;
            }
            else
            {
                var _userId = _webSecurity.CurrentUserId;
                var ForumIdAllowed = _forumIdAllowed(User.Identity.IsAuthenticated);
                var ForumCategoryAllowed = db.ForumCategorySet.Where(cat => ForumIdAllowed.Contains(cat.Forum_Id)).Select(cat2 => cat2.Id).ToList();
                var ForumTopicAllowed = db.ForumTopicSet.Where(topic => ForumCategoryAllowed.Contains(topic.ForumCategory_Id)).Select(topic2 => topic2.Id).ToList();
                List<Int32> ForumPostUnread = db.ForumPostSet.Where(post => ForumTopicAllowed.Contains(post.ForumTopic_Id)).Except(db.ForumPostSet.Where(post => post.ForumPostReadSet.Where(read => read.UserId == _userId).Count() > 0)).Select(post => post.Id).ToList();

                UnReadPostNumber = ForumPostUnread.Count();
                ForumPostUnreadNumber = String.Format("{0} {1}", UnReadPostNumber, CloudFranceTriple.WebRole.Properties.Resources.ForumPostUnreadNumber);
            }
            return PartialView("_UnreadMessage", ForumPostUnreadNumber);
        }

        //
        // GET: /Forum/PostRead/MarkAllAsRead

        [Authorize(Roles = "RoleMember,RoleFans,RoleBaffMember,RoleAdminForum")]
        public void MarkAllPostAsReadAsync()
        {
            var _userId = _webSecurity.CurrentUserId;
            var ForumIdAllowed = _forumIdAllowed(User.Identity.IsAuthenticated);
            var ForumCategoryAllowed = db.ForumCategorySet.Where(cat => ForumIdAllowed.Contains(cat.Forum_Id)).Select(cat2 => cat2.Id).ToList();
            var ForumTopicAllowed = db.ForumTopicSet.Where(topic => ForumCategoryAllowed.Contains(topic.ForumCategory_Id)).Select(topic2 => topic2.Id).ToList();
            List<Int32> ForumPostUnread = db.ForumPostSet.Where(post => ForumTopicAllowed.Contains(post.ForumTopic_Id)).Except(db.ForumPostSet.Where(post => post.ForumPostReadSet.Where(read => read.UserId == _userId).Count() > 0)).Select(post => post.Id).ToList();

            if (!_UserMarkingAllAsRead.Contains(_userId))
            {
                // Mettre ici un appel asynchrone !!!
                _MarkAllPostAsRead(_userId, ForumPostUnread);
            }
        }

        [Authorize(Roles = "RoleMember,RoleFans,RoleBaffMember,RoleAdminForum")]
        public ActionResult MarkAllPostAsReadCompleted()
        {
            return null;
        }

        private void _MarkAllPostAsRead(Int32 UserId, List<Int32> ForumPostAllowed)
        {
            _UserMarkingAllAsRead.Add(UserId);
            try
            {
                using (var ctx = new cloudfrAboq2RsDMEntities())
                {
                    var counter = 0;
                    foreach (Int32 postId in ForumPostAllowed)
                    {
                        ctx.ForumPostReadSet.Add(new ForumPostReadSet() { ForumPost_Id = postId, UserId = UserId });
                        if (counter++ % 200 == 0)
                            ctx.SaveChanges();
                    }
                    ctx.SaveChanges();
                }
            }
            finally
            {
                _UserMarkingAllAsRead.Remove(UserId);
            }
        }
    }
}